home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Workbench Add-On
/
Workbench Add-On - Volume 1.iso
/
BBS-Archive
/
Comm
/
AmiTCP30b2.lha
/
src
/
amitcp
/
kern
/
subr_prf.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-02-16
|
18KB
|
697 lines
RCS_ID_C="$Id: subr_prf.c,v 1.33 1994/02/16 06:07:33 jraja Exp $";
/*
* Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>,
* Helsinki University of Technology, Finland.
* All rights reserved.
*
* HISTORY
* $Log: subr_prf.c,v $
* Revision 1.33 1994/02/16 06:07:33 jraja
* Replaced RawDoFmt() calls with vcsprintf(), which now does the formatting
* itself. Changed stuffchar() to cs_putchar(), added csprintn() to print
* out numbers.
* Changed vlog() to return the number of characters written, changed
* printf() to use vlog() (wheir code was identical).
*
* Revision 1.32 1994/01/05 10:27:30 jraja
* Added IntuitionBase opening and closing to the panic().
* Note: using a local library base variable might not work in GCC?
*
* Revision 1.31 1993/12/21 22:06:48 jraja
* Changed implicit structure member (s_sec) to explicit (tv_secs) on timeval.
*
* Revision 1.30 1993/11/06 23:51:22 ppessi
* Added csprintf(), sprintf function using CSource.
* Added vsprintf() and vcsprintf() as well.
*
* Revision 1.29 1993/10/07 22:41:34 ppessi
* Added time to the log message.
*
* Revision 1.28 1993/05/16 00:11:12 jraja
* Removed redundant volatile keyword.
*
* Revision 1.27 93/05/14 15:54:17 15:54:17 ppessi (Pekka Pessi)
* Minor prototype fixes.
*
* Revision 1.26 93/05/05 16:10:15 16:10:15 puhuri (Markus Peuhkuri)
* Fixes for final demo.
*
* Revision 1.25 93/05/04 12:40:07 12:40:07 puhuri (Markus Peuhkuri)
* Fixed PANICBUFFER (SASC didnt like implicit alloca())
* Now log takes care of keeping level on right range.
*
* Revision 1.24 93/04/29 22:02:44 22:02:44 puhuri (Markus Peuhkuri)
* fixed variable names to use configuration structure.
*
* Revision 1.23 93/04/28 12:59:05 12:59:05 puhuri (Markus Peuhkuri)
* Fixed stdargs.h to stdarg.h
*
* Revision 1.22 93/04/27 10:23:19 10:23:19 puhuri (Markus Peuhkuri)
* Add vlog-function for calling log from API. log() calls now vlog().
*
* Revision 1.21 93/04/26 18:55:08 18:55:08 puhuri (Markus Peuhkuri)
* Moved contents of closelog to log_deinit() and removed closelog.
*
* Revision 1.20 93/04/26 11:54:46 11:54:46 too (Tomi Ollila)
* Changed include paths of amiga_api.h, amiga_libcallentry.h and amiga_raf.h
* from kern to api
*
* Revision 1.19 93/04/23 02:28:38 02:28:38 ppessi (Pekka Pessi)
* Number and length of logging messages made configureable.
*
* Revision 1.18 93/04/21 19:08:46 19:08:46 puhuri (Markus Peuhkuri)
* Now checks if process run into panic() was AmiTCP.
* Now uses new structure to log_msg. (Printing of priority is in
* NETTRACE)
*
* Revision 1.17 93/04/06 15:15:55 15:15:55 jraja (Jarno Tapio Rajahalme)
* Changed spl function return value storage to spl_t,
* changed bcopys and bzeros to aligned and/or const when possible,
* added inclusion of conf.h to every .c file.
*
* Revision 1.16 93/03/20 07:06:38 07:06:38 ppessi (Pekka Pessi)
* Fixed memory leak caused by task_remove()
*
* Revision 1.15 93/03/19 14:14:54 14:14:54 too (Tomi Ollila)
* Code changes at night 17-18 March 1993
*
* Revision 1.14 93/03/15 09:12:42 09:12:42 jraja (Jarno Tapio Rajahalme)
* Checkin' mods made by ppessi.
*
* Revision 1.13 93/03/13 00:05:31 00:05:31 ppessi (Pekka Pessi)
* Quick'n'dirty fix for PANICBUFFER; some prototypes fixed.
*
* Revision 1.12 93/03/10 17:14:12 17:14:12 puhuri (Markus Peuhkuri)
* Fixed documentation. Now (s)printf returns number of printed chars.
*
* Revision 1.11 93/03/09 13:33:11 13:33:11 puhuri (Markus Peuhkuri)
* See messages for amiga_log.c/1.10.
* Now uses new function to get log message.
* Fixed a bug in closing of log (caused a read from low memory, 0x14)
*
* Revision 1.10 93/03/05 21:11:17 21:11:17 jraja (Jarno Tapio Rajahalme)
* Fixed includes (again).
*
* Revision 1.9 93/03/05 12:32:33 12:32:33 jraja (Jarno Tapio Rajahalme)
* Removed #include <kern/amiga_api_protos.h>.
*
* Revision 1.8 93/03/05 03:26:17 03:26:17 ppessi (Pekka Pessi)
* Compiles with SASC. Initial test version.
*
* Revision 1.7 93/03/02 18:25:12 18:25:12 puhuri (Markus Peuhkuri)
* Add sprintf() and fixed documentation
*
* Revision 1.6 93/03/02 16:10:35 16:10:35 puhuri (Markus Peuhkuri)
* Removed amiga.lib functions, fixed memory managment
*
* Revision 1.5 93/02/26 19:44:35 19:44:35 puhuri (Markus Peuhkuri)
* Modified to use MsgPort as list of free messages,
* made log() and printf() re-entrant, removed kprintf (replaced w/
* exec/RawDoFmt()), kernputchar, ksprintn() and logpri.
* As every BSD/Mach code was removed so was copyright.
*
* Revision 1.4 93/02/25 19:39:25 19:39:25 puhuri (Markus Peuhkuri)
* Includes fixed, compatible with both GCC and SAS,
* function declarations fixed, calls from panic() fixed,
* checks for various places.
*
* Revision 1.3 93/02/24 17:32:17 17:32:17 puhuri (Markus Peuhkuri)
* Add printf (for printing to log)
*
* Revision 1.2 93/02/24 17:22:23 17:22:23 puhuri (Markus Peuhkuri)
* Made program to work much cleanier, still uses Amiga.lib
*
* Revision 1.1 92/12/17 18:19:42 puhuri
* Initial revision
*
*/
#include <conf.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/syslog.h>
#include <sys/time.h>
#include <kern/amiga_includes.h>
#include <api/amiga_api.h>
#include <api/amiga_libcallentry.h>
#include <kern/amiga_log.h>
#include <stdarg.h>
#include <intuition/intuition.h>
#if __GNUC__
#include <inline/intuition.h>
#elif __SASC
#include <proto/intuition.h>
#endif
#include <kern/amiga_main_protos.h>
#include <dos/rdargs.h> /* CSource */
extern void exit(int);
void
cs_putchar(unsigned char ch, struct CSource * cs)
{
if (cs->CS_CurChr < cs->CS_Length
&& (cs->CS_Buffer[cs->CS_CurChr] = ch))
cs->CS_CurChr++;
}
/****i* bsdsocket.library/panic ******************************************
*
* NAME
* panic -- Inform user from serious failure.
*
* SYNOPSIS
* panic(Message, Arguments...)
*
* void panic( STRPTR, ... )
*
* FUNCTION
* Calls api_setfunctions() with no arguments to stop programs using
* AmiTCP. Writes message to log file. Sets up User Requester to
* inform user about situation. Avoids self-loops.
*
*
* INPUTS
* Messagestring - A pointer to string containing message to show
* to user and to write to log. It should describe problem so
* that user can take correcting action if it is failure with
* his configuration or is able to write bug report if it is
* a bug withn program.
*
* Arguments - as in c-library printf()
*
* RESULT
* This function does not return.
*
* EXAMPLE
* if(Everything==WRONG)
* panic("Everything is wrong\nGoto sleep");
*
* NOTES
* As panic does not return, it should be used only in extreme
* cases
*
* BUGS
*
* SEE ALSO
* log()
*
******************************************************************************
*
*/
#define PANICBUFFERSIZE 512
void
panic(const char *fmt,...)
{
struct EasyStruct panicES = {
sizeof( struct EasyStruct),
NULL,
"AmiTCP PANIC",
"panic: %s" ,
"Exit AmiTCP"
};
static in_panic = 0;
struct CSource cs;
char buffer[PANICBUFFERSIZE];
va_list ap;
struct Library *IntuitionBase = NULL; /* local intuitionbase */
extern struct Task *AmiTCP_Task;
if (!in_panic){
/* If we're called previously.. */
in_panic++; /* We're in panic now */
api_setfunctions(); /* Set libraries to return error code */
cs.CS_Buffer = buffer;
cs.CS_CurChr = 0;
cs.CS_Length = PANICBUFFERSIZE;
va_start(ap, fmt);
vcsprintf(&cs, fmt, ap);
va_end(ap);
log(LOG_EMERG, "panic: %s", buffer); /* Write to log */
}
in_panic--;
/*
* Inform user (if log system has failed...)
* by opening a requester to the default public screen.
*
* Open a local IntuitionBase for the EasyRequestArgs()
*/
if ((IntuitionBase = OpenLibrary("intuition.library", 37L)) != NULL) {
EasyRequestArgs(NULL, &panicES, NULL, (char *)&buffer);
CloseLibrary(IntuitionBase);
IntuitionBase = NULL;
}
/*
* If the caller is not the AmiTCP task, sleep forever.
* This should go to API or where ever we came in AmiTCP code
*/
if (FindTask(NULL) != AmiTCP_Task)
Wait(0);
Wait(SIGBREAKF_CTRL_F); /* AmiTCP/IP waits here */
/*
* Following code is not safe. Probably we should wait infinetely long too...
*/
deinit_all(); /* This returns !! */
exit(20); /* This should be safe... */
}
/****i* bsdsockets.library/log ******************************************
*
* NAME
* log -- Write log message to log and/or console.
*
* SYNOPSIS
* log(Level, FormatString, arguments...)
*
* void log( ULONG, STRPTR, ...)
*
* FUNCTION
* Writes message given as format string and arguments
* (printf-style) to both log and console (except if level is
* LOG_EMERG, LOG_EMERG is generated only by panic and it is
* written only to the log file as panic() generates an User
* Requester informing user.
*
* This function can be called from interrupts.
*
* INPUTS
* Level - indicates type of logged message. These levels are
* defined in sys/syslog.h.
* FormatString - This is a printf-style format string with some
* restrictions (notably the floats are not handled).
* arguments - as in printf()
*
* RESULT
* Returns no value.
*
* EXAMPLE
* log(LOG_ERR,
* "arp: ether address is broadcast for IP address %x!\n",
* ntohl(isaddr.s_addr));
* fail=TRUE;
* break;
*
* NOTES
*
* BUGS
*
* SEE ALSO
* Your C-compilers printf() documentation.
*
******************************************************************************
*
*/
void
log(unsigned long level, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vlog(level, fmt, ap); /* Call actual function */
va_end(ap);
}
ULONG
vlog(unsigned long level, const char *fmt, va_list ap)
{
struct log_msg *msg;
struct timeval now;
if (msg = (struct log_msg *)GetLogMsg(logReplyPort)) {
ULONG ret;
struct CSource cs;
cs.CS_Buffer = msg->string;
cs.CS_Length = log_cnf.log_buf_len;
cs.CS_CurChr = 0;
GetSysTime(&now);
vcsprintf(&cs, fmt, ap);
msg->level = level & (LOG_FACMASK | LOG_PRIMASK); /* Level of message */
ret = msg->chars = cs.CS_CurChr;
msg->time = now.tv_secs;
PutMsg(logPort, (struct Message *)msg);
return ret;
}
return 0;
}
/****i* bsdsockets.library/printf ******************************************
*
* NAME
* printf -- print to log
*
* SYNOPSIS
* printf(FormatString, Arguments...)
*
* ULONG printf( const char *, ...)
*
* FUNCTION
* Prints messages to log
* As log, also this is callable from interrupts.
*
* Specially for debugging prints.
*
* INPUTS
* FormatString - This is a printf-style format string as for vcsprintf().
* Arguments - as in C-librarys printf()
*
* RESULT
* Number of characters printed.
*
* EXAMPLE
*
* printf("line=%d, val=%x\n",
* __LINE__, very.interesting->value);
*
* NOTES
*
* BUGS
*
* SEE ALSO
* vcsprintf(), vlog()
*
******************************************************************************
*
*/
ULONG
printf(const char *fmt, ...)
{
#if 1
ULONG ret;
va_list ap;
va_start(ap, fmt);
ret = vlog(LOG_INFO, fmt, ap);
va_end(ap);
return ret;
#else
va_list ap;
struct log_msg *msg;
struct timeval now;
if (msg = GetLogMsg(logReplyPort)) { /* Get next free message */
struct CSource cs;
GetSysTime(&now);
cs.CS_Buffer = msg->string;
cs.CS_Length = log_cnf.log_buf_len;
cs.CS_CurChr = 0;
va_start(ap, fmt);
vcsprintf(&cs, fmt, ap);
va_end(ap);
msg->level = LOG_INFO;
msg->chars = cs.CS_CurChr;
msg->time = now.tv_secs;
PutMsg(logPort,(struct Message *)msg);
return (ULONG)cs.CS_CurChr;
} else
return 0;
#endif
}
/****i* bsdsockets.library/sprintf ******************************************
*
* NAME
* sprintf -- print to buffer
*
* SYNOPSIS
* len = sprintf(Buffer, FormatString, Arguments...)
* len = csprintf(cs, FormatString, Arguments...)
*
* ULONG sprintf(STRPTR, const char*, ...)
* ULONG csprintf(struct CSource *, const char*, ...)
*
* FUNCTION
* Prints to a simple buffer or to a CSource buffer. These functions
* are similar to C-library sprintf() with restricted formatting.
*
* INPUTS
* Buffer - Pointer to buffer.
* FormatString - This is a printf()-style format string with some
* restrictions. Numbers are being taken as 'long' by
* default, however.
* Arguments - as in printf() .
* cs - Pointer to CSource structure.
*
* RESULT
* Number of characters printed.
*
* EXAMPLE
* sprintf(mybuf, "line=%d, val=%x\n",
* __LINE__, very.interesting->value);
*
* BUGS
* Function sprintf() assumes that no print is longer than 1024 chars.
* It does not check for buffer owerflow (there no way to check, the
* definition of sprintf misses it).
*
* sprintf strings are truncated to maximum of 1024 chars (including
* final NUL)
*
* SEE ALSO
* vcsprintf()
*
******************************************************************************
*
*/
ULONG
vcsprintf(struct CSource *cs, const char *fmt, va_list ap)
{
ULONG start = cs->CS_CurChr;
char *p, ch, padc;
u_long ul;
int n, base, lflag, tmp, width, precision, leftjustify;
char buf[sizeof(long) * NBBY / 3 + 2]; /* A long in base 8, plus '\0'. */
if (cs->CS_Length && cs->CS_CurChr < cs->CS_Length) {
for (;;) {
padc = ' ';
width = 0;
precision = -1;
leftjustify = FALSE;
while ((ch = *fmt++) != '%') {
if (ch == '\0') {
goto end;
}
cs_putchar(ch, cs);
}
lflag = 0;
reswitch:
switch (ch = *fmt++) {
case '-':
leftjustify = TRUE;
goto reswitch;
case '0':
padc = '0';
goto reswitch;
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
for (width = 0;; ++fmt) {
width = width * 10 + ch - '0';
ch = *fmt;
if (ch < '0' || ch > '9')
break;
}
goto reswitch;
case '.': /* precision */
for (precision = 0; (ch = *fmt) >= '0' && ch <= '9'; ++fmt) {
precision = precision * 10 + ch - '0';
}
goto reswitch;
case 'l':
lflag = 1;
goto reswitch;
case 'b':
{
char *tp;
ul = va_arg(ap, int);
p = va_arg(ap, char *);
for (tp = csprintn(ul, *p++, buf, sizeof(buf)); ch = *tp++;)
cs_putchar(ch, cs);
if (!ul)
break;
for (tmp = 0; n = *p++;) {
if (ul & (1 << (n - 1))) {
cs_putchar(tmp ? ',' : '<', cs);
for (; (n = *p) > ' '; ++p)
cs_putchar(n, cs);
tmp = 1;
} else
for (; *p > ' '; ++p)
;
}
if (tmp)
cs_putchar('>', cs);
}
break;
case 'r':
p = va_arg(ap, char *);
vcsprintf(cs, p, va_arg(ap, va_list));
break;
case 'c':
*buf = va_arg(ap, int);
buf[1] = '\0';
p = buf;
goto textout;
case 's':
p = va_arg(ap, char *);
textout:
/*
* Set width to the maximum width, if maximum width is set, and
* width exceeds it.
*/
if (precision > 0 && width > precision)
width = precision;
/*
* spit out necessary pad characters to fill on left, if necessary
*/
if (width > 0 && !leftjustify && (width -= strlen(p)) > 0)
while (width--)
cs_putchar(padc, cs);
/* take a copy of the original pointer */
ul = (u_long)p;
/*
* Copy the characters, pay attention to the fact that precision
* may not be exceeded.
*/
while ((ch = *p++) && precision-- != 0)
cs_putchar(ch, cs);
/*
* spit out necessary pad characters to fill on right, if necessary
*/
if (width > 0 && leftjustify && (width -= ((u_long)p - ul - 1)) > 0)
while (width--)
cs_putchar(' ', cs);
break;
case 'd':
case 'i':
ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
if ((long)ul < 0) {
cs_putchar('-', cs);
ul = -(long)ul;
}
base = 10;
goto number;
case 'o':
ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
base = 8;
goto number;
case 'u':
ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
base = 10;
goto number;
case 'p': /* pointers */
case 'P':
width = 8;
padc = '0';
/* FALLTHROUGH */
case 'x':
case 'X':
ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
base = 16;
number:
p = csprintn(ul, base, buf, sizeof(buf));
tmp = (buf + sizeof(buf) - 1) - p; /* length */
if (width > 0 && !leftjustify && (width -= tmp) > 0)
while (width--)
cs_putchar(padc, cs);
while (ch = *p++)
cs_putchar(ch, cs);
if (width > 0 && leftjustify && (width -= tmp) > 0)
while (width--)
cs_putchar(' ', cs);
break;
default:
cs_putchar('%', cs);
if (lflag)
cs_putchar('l', cs);
/* FALLTHROUGH */
case '%':
cs_putchar(ch, cs);
}
}
end:
if (cs->CS_CurChr == cs->CS_Length) {
cs->CS_CurChr--; /* must NUL terminate */
}
cs->CS_Buffer[cs->CS_CurChr] = '\0';
return cs->CS_CurChr - start;
} else {
/* A pathological case */
return 0;
}
}
ULONG csprintf(struct CSource *cs, const char *fmt, ...)
{
va_list ap;
ULONG len;
va_start(ap, fmt);
len = vcsprintf(cs, fmt, ap);
va_end(ap);
return len;
}
ULONG vsprintf(char *buf, const char *fmt, va_list ap)
{
struct CSource cs;
cs.CS_Buffer = buf;
cs.CS_CurChr = 0;
cs.CS_Length = 1024; /* This is not probably the cleanest way :-) */
return vcsprintf(&cs, fmt, ap);
}
ULONG sprintf(char *buf, const char *fmt, ...)
{
va_list ap;
ULONG len;
va_start(ap, fmt);
len = vsprintf(buf, fmt, ap);
va_end(ap);
return len;
}
char *
csprintn(u_long n, int base, char *buf, int buflen)
{
register char *cp = buf + buflen - 1;
*cp = 0;
do {
cp--;
*cp = "0123456789abcdef"[n % base];
} while (n /= base);
return (cp);
}